
/**
**************************************************************************
*/
//#pragma once

#include "Common.h"

__shared__ float CurBlockLocal1[BLOCK_SIZE2];
__shared__ float TargetBlockLocal2[BLOCK_SIZE2];


/* Read Pixel Value*/

__device__ float readPixVal( float* ImgSrc,int ImgWidth,int x,int y)
{
return (float)ImgSrc[y*ImgWidth+x];
}

__device__ void returnPixVal( float* ImgDst, float pixel, int ImgWidth,int x,int y)
{
	ImgDst[ImgWidth*y+x] = pixel;
}

__global__ void CUDAkernel_Swirl(float *Src,float *Dst, int ImgWidth)
{
    	// Block index
 	const int bx = blockIdx.x ;
	const int by = blockIdx.y ;

    	// Thread index (current coefficient)
    	const int tx = threadIdx.x;
    	const int ty = threadIdx.y;

	int pixi = bx*blockDim.x + tx; 
	int pixj = by*blockDim.y + ty; 


	float pixel = readPixVal(Src,ImgWidth, pixi, pixj);
	CurBlockLocal1[tx+ty*BLOCK_SIZE] = pixel; 
	
	//copy current image pixel to the first block
	// Read values into CurBlockLocal1 with readPixVal(Src,ImgWidth, tex_x, tex_y);


	//synchronize threads to make sure the block is copied
	__syncthreads();


	// Makes center of plane 0,0
	double newX = (double)pixi - ((double)ImgWidth)/2;
	double newY = (double)pixj - ((double)ImgWidth)/2;

	// Gets original angle
	double origAng = atan(newY/newX); 

	// Gets radius
	double radius = sqrt(newX*newX+newY*newY); 

	double strength = 1;	// Strength of swirl

	// Calculates angle offset using radius
	double offsetAng = radius/strength; 

	// Find pixel we must get
	int getX = radius*cos(origAng+offsetAng) + ((double)ImgWidth)/2;
	int getY = radius*sin(origAng+offsetAng) + ((double)ImgWidth)/2;
/*
	// Ensure pixels are within limits of block
	if(getX >= ImgWidth)
		getX = ImgWidth - 1;
	if(getX < 0)
		getX = 0; 
	if(getY >= ImgWidth)
		getY = ImgWidth - 1;
	if(getY < 0)
		getY = 0; 
*/
	// Ensure pixels are within limits of block
	if(getX >= BLOCK_SIZE)
		getX = BLOCK_SIZE - 1;
	if(getX < 0)
		getX = 0; 
	if(getY >= BLOCK_SIZE)
		getY = BLOCK_SIZE - 1;
	if(getY < 0)
		getY = 0; 

	TargetBlockLocal2[tx+ty*BLOCK_SIZE] = CurBlockLocal1[getX+getY*BLOCK_SIZE];
	//TargetBlockLocal2[tx+ty*BLOCK_SIZE] = readPixVal(Src,ImgWidth, getX, getY);
	
	returnPixVal(Dst, TargetBlockLocal2[ty*BLOCK_SIZE+tx], ImgWidth, pixi, pixj); 
	//returnPixVal(Dst, CurBlockLocal1[ty*BLOCK_SIZE+tx], ImgWidth, getX, getY); 
	
		
	
	



/*This is to copy the operated block to the destination image
Use a similar function like readPixVal called putPixVal
A smarter way is to copy all the block into the Dst array in parallel.. I will   leave that for you to discover.
*/

}


